package funciones;

public class DLG {
	/**
	 * lambdas con los que trabaja
	 */
	public double la1,la2,la3,la4;
	/**
	 * da la exactitud para el met. numerico para hallar u, maxVerosimilitud
	 */
	public static double TOLERANCIA_U;

	public DLG() {
		la1=0;la2=1;la3=0.13;la4=0.13;
		TOLERANCIA_U=1e-3;
	}

	//pre: todos los metodos requieren que previamente
	//se den los valores a cada lambda

	public double fpercentil(double u){
		return la1 + (Math.pow(u,la3) - Math.pow(1 - u,la4))/la2;
	}
	/**
	 * @param u
	 * @return la2/( la3*u^(la3-1) + la4*(1-u)^(la4-1) )
	 */
	public double fdensidad(double u){
		return la2 / ( la3*Math.pow(u,la3 - 1) + la4*Math.pow(1 - u,la4 - 1) );
	}

	/**
	 * ( la3*Math.pow(u,la3 - 1) + la4*Math.pow(1 - u,la4 - 1) ) / la2
	 * @param u
	 * @return
	 */
	public double derivadafpercentil(double u) {
		return 1/fdensidad(u);
	}

	/**
	 * valida lambda2, lambda3 y lambda4  
	 * @return
	 */
	public boolean sonLambdasValidos(){
		if(la2==0) return false;

		if (la3*la4 >= 0)               	    return true;
		else if ((la3>=1) && (la4<=-1))     	return true;
		else if ((la3<=-1) && (la4>=1))			return true;
		else if ((la3<0) && (la4>0) && (la4<1))	return false;
		else if ((la4<0) && (la3>0) && (la3<1))	return false;

		else if ((la3>-1) && (la3<0) && (la4>=1))                          //region 5

			if ( (Math.pow((1-la3),(1-la3))*Math.pow((1-la4), (1-la4)))/(Math.pow((la4-la3), (la4-la3))) < -la3/la4 ) 
				return true;
			else
				return false;

		else if ((la4>-1) && (la4<0) && (la3>=1))                         //region 6
			if ( (Math.pow((1-la4), (1-la4))*Math.pow((1-la3), (1-la3)))/(Math.pow((la3-la4), (la3-la4))) < -la4/la3 ) 
				return true;
			else
				return false;
		else                                                            
			return false;
	}
	/**
	 * @param alfa:significancia
	 * @return
	 */
	public double calcularValorCritico(double alfa){
		double u; 
		u=1-alfa;
		return fpercentil(u);
	}

	/**
	 * usa biseccion: no siempre hay solucion
	 * @param x
	 * @return u: x=fPercentil(u), # entre [0,1]
	 */
	public double calcularU(double x) {
		double a=0,b=1,c=0.5;
		while(b-a > TOLERANCIA_U){
			c = (a+b)/2d;
			if(Math.abs(fpercentil(c)-x) < TOLERANCIA_U){
				return c;
			}
			if((fpercentil(a)-x)*(fpercentil(c)-x) < 0){
				b = c;
			}else{
				a = c;
			}
		}
		return c;
	}

	/**
	 * usa Newton-Raphson
	 * @param x
	 * @return
	 */
	public double calcularU_NR(double x) {
		double u=Math.random();
		while(Math.abs(fpercentil(u))>1e-5){
			u = u - (fpercentil(u)-x) / derivadafpercentil(u);
		}
		return u;
	}
}